#pragma once
//系统头文件
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<strings.h>

//标准库头文件
#include<iostream>
#include<string>
#include<filesystem>
#include<cstdlib>
#include<functional>
//其他头文件
#include"Logger.hpp"

static const int gdefaultsockfd = -1;

using callback_t = std::function<std::string \
                (const std::string& word , const std::string& whoip, uint16_t whoport)>;

class DictServer
{
public:
    //构造
    DictServer(uint16_t port , callback_t cb)
    :_port(port)
    ,_sockfd(gdefaultsockfd)
    ,_isrunning(false)
    ,_cb(cb)
    {}
    void Init()
    {
        //1、创建socket fd
        _sockfd = socket(AF_INET , SOCK_DGRAM , 0);//返回值为文件描述符
        if(_sockfd < 0)
        {
            //失败
            LOG(LogLevel::FATAL) << "create socket error";
            exit(1);
        }
        //成功
        LOG(LogLevel::INFO)<<"create socket success";

        //2、bind
        //2.1 填充IP和Port
        struct sockaddr_in local;
        bzero(&local , sizeof(local));//将结构体置空
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        //服务器接收所有客户端的ip
        local.sin_addr.s_addr = htonl(INADDR_ANY);

        //2.2 与sockfd 进行bind
        //#include<sys/socket.h>   int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 返回值：成功返回0，失败返回-1
        int n = bind(_sockfd , (struct sockaddr*)&local ,sizeof(local));
        if(n<0)
        {
            LOG(LogLevel::FATAL) << "bind socket error";
            exit(2);
        }
        LOG(LogLevel::INFO) <<"bind socket success : " << _sockfd;
    }

    void Start()
    {
        //所有的服务器均是死循环
        _isrunning = true;
        while(_isrunning)
        {
            char buffer[1024];
            buffer[0] = 0;//清空缓冲区
            struct sockaddr_in peer;//读取数据时的输出型参数
            socklen_t len = sizeof(peer);
            //读取数据
            //#include<sys/socket.h>        ssize_t recvfrom(int sockfd, void buf[restrict .len], size_t len,int flags,
            //struct sockaddr *_Nullable restrict src_addr,socklen_t *_Nullable restrict addrlen);
            //返回值为成功读取的字节数

            // std::cout << "开始读取" <<std::endl;

            ssize_t n = recvfrom(_sockfd , buffer,sizeof(buffer),0 , (struct sockaddr*)&peer,&len);
            // std::cout << "server 读取成功: " << buffer <<std::endl;

            if(n > 0)
            {
                buffer[n] = 0;

                //读取成功，将信息返回给客户端
                uint16_t clientport = ntohs(peer.sin_port);
                std::string clientip = inet_ntoa(peer.sin_addr);

                // std::cout << "server 读取成功: " << buffer <<std::endl;

                std::string word = buffer;
                LOG(LogLevel::DEBUG) << "用户查找： " << word;
                //回调
                std::string result = _cb(word , clientip ,clientport);

                // std::cout<<"开始传回" <<std::endl;

                //服务端将数据传回给客户端
                //#include<sys/sockrt.h>  ssize_t sendto(int sockfd, const void buf[.len], size_t len, int flags,
                //const struct sockaddr *dest_addr, socklen_t addrlen);
                sendto(_sockfd , result.c_str(), result.size(),0 , (struct sockaddr*)&peer , len);

                // std::cout<<"传给客户端成功" <<std::endl;

            }
        }
        _isrunning = false;
    }
    void Stop()
    {
        _isrunning = false;
    }
    //析构
    ~DictServer()
    {};
private:
    int _sockfd;
    uint16_t _port;
    callback_t _cb;
    bool _isrunning;
};
